package com.platform.module.user.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.platform.module.common.base.CodeEnum;
import com.platform.module.common.constant.CacheConstant;
import com.platform.module.common.redis.CacheClient;
import com.platform.module.common.resp.UserTokenResp;
import com.platform.module.common.utils.AssertUtils;
import com.platform.module.common.utils.MD5Helper;
import com.platform.module.common.utils.ValidatorUtils;
import com.platform.module.dao.entity.TbUser;
import com.platform.module.dao.entity.TokenRecord;
import com.platform.module.dao.service.TbUserService;
import com.platform.module.pojo.UserRecord;
import com.platform.module.dao.mapper.UserMapper;
import com.platform.module.pojo.user.dto.RegisterDto;
import com.platform.module.pojo.user.vo.LoginVo;
import com.platform.module.user.service.TokenService;
import com.platform.module.user.service.UserTokenService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.UUID;
import java.util.regex.Pattern;

/**
 * @author Long
 **/
@Slf4j
@Service
public class UserTokenServiceImpl implements UserTokenService {

    private final UserMapper userMapper;
    private final TbUserService tbUserService;
    private final CacheClient cacheClient;
    private final TokenService tokenService;

    public UserTokenServiceImpl(CacheClient cacheClient,
                                TokenService tokenService,
                                UserMapper userMapper,
                                TbUserService tbUserService) {
        this.cacheClient = cacheClient;
        this.tokenService = tokenService;
        this.userMapper = userMapper;
        this.tbUserService = tbUserService;
    }


    @Override
    public UserTokenResp setUserToken(Long userId, String token) {
        log.info("设置用户token缓存，userId:{}", userId);
        UserTokenResp resp = new UserTokenResp();
        if (userId == null) {
            log.error("账户信息为null，不设置user缓存，不生成token");
            return null;
        }

        UserRecord user = this.userMapper.findUserByUid(userId);
        if (user != null && user.getUserId() != null) {
            String prefix = "prefix";
            if (StringUtils.isBlank(token)) {
                this.tokenService.updateStateLogout(userId);
                TokenRecord tokenRecord = this.tokenService.generateNewToken(user, prefix);
                token = tokenRecord.getCaccesstoken();
                this.cacheClient.setDays(CacheConstant.USER_LOGIN_TOKEN + user.getUserId(), token, 90L);
                String cookieKey = UUID.randomUUID().toString().replace("-", "")
                        + System.currentTimeMillis()
                        + RandomUtil.randomInt(100000, 999999);
                this.cacheClient.setDays(CacheConstant.USER_LOGIN_COOKIEKEY + user.getUserId(), cookieKey, 90L);
                log.info("创建token成功, userId={} token={}", userId, token);
                resp.setCaccesstoken(token);
                resp.setCkky(cookieKey);
            } else {
                this.cacheClient.setDays(CacheConstant.USER_LOGIN_TOKEN + user.getUserId(), token, 90L);
                String cookieKey = this.cacheClient.getStr(CacheConstant.USER_LOGIN_COOKIEKEY + userId);
                if (StringUtils.isBlank(cookieKey)) {
                    log.info("续期token失败, userId={} registerType={} token={}", userId, user.getRegisterType(), token);
                } else {
                    this.cacheClient.setDays(CacheConstant.USER_LOGIN_COOKIEKEY + userId, cookieKey, 90L);
                    resp.setCkky(cookieKey);
                    log.info("续期token成功, userId={} registerType={} token={}", userId, user.getRegisterType(), token);
                }

                resp.setCaccesstoken(token);
            }

            return resp;
        }

        log.error("账户信息为null，不设置user缓存，不生成token,userId：{}", userId);
        return null;
    }

    @Override
    public LoginVo phoneLogin(String phone, String password) {
        log.info("手机号登录，phone:{} password:{}", phone, password);

        // 将phone和password进行md5加密
        String phoneMd5 = MD5Helper.md5Hex(phone);
        String passwordMd5 = MD5Helper.md5Hex(password);

        // 先校验密码，在检查账户状态
        TbUser tbUser = tbUserService.findUserByCmobilenomd5(phoneMd5);
        AssertUtils.assertNotNull(tbUser, CodeEnum.账号不存在);
        AssertUtils.assertTrue(tbUser.getCpassword().equals(passwordMd5), CodeEnum.密码错误);
        AssertUtils.assertNotEquals(tbUser.getIstate(), 1,CodeEnum.账户已冻结);
        AssertUtils.assertNotEquals(tbUser.getIstate(), 2,CodeEnum.账户已注销);

        UserTokenResp userTokenResp = setUserToken(tbUser.getUserId(), null);
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(userTokenResp.getCaccesstoken());
        loginVo.setSign(userTokenResp.getCkky());
        return loginVo;
    }

    @Override
    public Boolean phoneRegisterDto(RegisterDto registerDto) {
        log.info("手机号注册，phone:{} password:{} cnickname:{} crealname:{}", registerDto.getPhone(),
                registerDto.getPassword(), registerDto.getCnickname(), registerDto.getCrealname());

        // 将phone和password进行md5加密
        String phoneMd5 = MD5Helper.md5Hex(registerDto.getPhone());
        String passwordMd5 = MD5Helper.md5Hex(registerDto.getPassword());

        TbUser tbUser = tbUserService.findUserByCmobilenomd5(phoneMd5);
        AssertUtils.assertNull(tbUser, CodeEnum.用户已存在请登录);

        LocalDateTime now = LocalDateTime.now();
        String cmobileno = registerDto.getPhone().substring(registerDto.getPhone().length() - 4);
        TbUser entity = new TbUser();
        entity.setCadddateTime(now);
        entity.setCnickname(registerDto.getCnickname());
        entity.setCrealname(registerDto.getCrealname());
        entity.setCmobileno(cmobileno);
        entity.setCmobilenomd5(phoneMd5);
        entity.setCpassword(passwordMd5);
        entity.setIbindMobile(1);
        return tbUserService.save(entity);
    }

}
